<template>
    <div class="mainContainer">
        <!--这里使用了scroll-behavior: smooth;作平滑滚动-->
        <div class="wrapper" ref="wrapper">
            <div class="section">section1 content</div>
            <div class="section">section2 content</div>
            <div class="section">section3 content</div>
            <div class="section">section4 content</div>
            <div class="section">section5 content</div>
        </div>
        <nav class="navMenu">
            <a :class="[addActiveClass(0)]" @click="onTabClick(0)">section1</a>
            <a :class="[addActiveClass(1)]" @click="onTabClick(1)">section2</a>
            <a :class="[addActiveClass(2)]" @click="onTabClick(2)">section3</a>
            <a :class="[addActiveClass(3)]" @click="onTabClick(3)">section4</a>
            <a :class="[addActiveClass(4)]" @click="onTabClick(4)">section5</a>
        </nav>
    </div>
</template>

<script>
    let handlerScroll = null;
    let clearSetTimeoutKey = null;
    export default {
        name: "ScrollNavPosition",
        data: () => {
            return {
                curSelected: 0
            }
        },
        methods: {
            onTabClick: function (idx) {
                const sectionDivDomArr = document.getElementsByClassName('section');
                sectionDivDomArr.item(idx)?.scrollIntoView(true);
            },
            addActiveClass: function (idx) {
                return idx === this.curSelected ? 'tabSelected' : ''
            },
            onScroll: function (offsetTopArr) {
                const scrollTop = this.$refs.wrapper.scrollTop;
                for (let i = offsetTopArr.length - 1; i >= 0; i--) {
                    const sectionOffsetTop = offsetTopArr[i];
                    if (scrollTop >= (sectionOffsetTop - 60)) {
                        // 如果滚动条已经滚动到了底部,且i依然不等于最后一个标签的索引,则高亮最后一个标签
                        const isScrollBottom = this.$refs.wrapper.scrollHeight === scrollTop + this.$refs.wrapper.clientHeight;
                        if (i !== (offsetTopArr.length - i) && isScrollBottom) {
                            this.curSelected = offsetTopArr.length - 1;
                        } else {
                            this.curSelected = i;
                        }
                        break;
                    }
                }
            }
        },
        mounted() {
            const sectionDivDomArr = document.getElementsByClassName('section');
            const offsetTopArr = [];
            handlerScroll = () => {
                if (clearSetTimeoutKey) clearTimeout(clearSetTimeoutKey)
                clearSetTimeoutKey = setTimeout(() => {
                    // 注意: 这个 offsetTop 只能在回调函数里面获取, 如果放到滚动监听函数之外, 获取到的数据, 并非预期的值
                    for (let i = 0; i < sectionDivDomArr.length; i++) {
                        offsetTopArr[i] = sectionDivDomArr.item(i).offsetTop;
                    }
                    this.onScroll(offsetTopArr);
                }, 30)
            }
            this.$refs.wrapper.addEventListener('scroll', handlerScroll)
        },
        beforeDestroy() {
            if (clearSetTimeoutKey) clearTimeout(clearSetTimeoutKey)
            this.$refs.wrapper.removeEventListener('scroll', handlerScroll)
        }
    }
</script>

<style lang="scss" scoped>
    @import "ScrollNavPosition";
</style>
